package cn.autumnorange.app.common.consumer.gts;

import com.taobao.txc.client.aop.annotation.TxcTransaction;
import lombok.extern.slf4j.Slf4j;
import org.aspectj.lang.ProceedingJoinPoint;
import org.aspectj.lang.annotation.Around;
import org.aspectj.lang.annotation.Aspect;
import org.aspectj.lang.reflect.MethodSignature;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.core.annotation.Order;
import org.springframework.stereotype.Component;

import java.lang.reflect.Method;

/** 注意TxcTransaction注解已被gts 异常aop处理 本setXidAop必须后执行 */
@Aspect
@Order(500)
@Component
@Slf4j
public class GtsConsumerGenerateXIDAspect {
  @Autowired private GtsConsumerService gtsConsumerServiceImpl;

  private final String ExpGetResultDataPonit =
      "@annotation(com.taobao.txc.client.aop.annotation.TxcTransaction)";

  @Around(ExpGetResultDataPonit)
  public Object around(ProceedingJoinPoint point) throws Throwable {
    Object result = null;
    Exception exception = null;
    try {
      // 可以做一些前置处理
      String xid = gtsConsumerServiceImpl.setXidToHeader();
      //      切面介入工作....前置通知 消费端
      log.info("分布式事务xid 创建结果:{}", xid);
      Object[] args = point.getArgs(); // 获取目标方法的所有参数的值
      // 拿到注解的值
      MethodSignature signature = (MethodSignature) point.getSignature();
      Method method = signature.getMethod();
      TxcTransaction annotation = method.getAnnotation(TxcTransaction.class);

      // 根据你的需求获取标注在注解的值
      //      String key = annotation.key();
      int timeOut = annotation.timeout();
      //      切面介入工作....前置通知 消费端
      //      log.info("get timeOut:" + timeOut);

      if (args != null && args.length > 0) {
        // 根据你的需求获取被切方法的args参数
      }
      // 目标方法真正执行...
      result = point.proceed(args);
      // todo 根据你的实际需要，做真正的处理，
      //      log.info("切面介入工作....返回通知");
    } catch (Exception e) {
      //      log.info("切面介入工作....异常通知");
      exception = e;
    } finally {
      if (exception != null) {
        // 需要抛出该异常,声明了@TxcTransaction注解 猜测GTS有其自己的aop 会处理该异常并通知tc全局回滚事务
        if (exception instanceof RuntimeException) {
          throw exception;
        } else {
          throw new RuntimeException(exception);
        }
      }
      String xid = gtsConsumerServiceImpl.removeXidByHeader();
      // 做一些善后工作
      //      "切面介入工作....后置通知 finally一次完整消费端调用生产端结束
      // header头移除gts全局事务id,用来防止feign调用时重试仍使用已经提交的gtx事务xid"
      log.info("分布式事务xid:{} 移除:", xid);
    }
    return result;
  }
}
